<?php

namespace XWAM\Addon\PXCallSystem\Controller;

/**
 * 队列控制器
 *
 * @author Alen
 * @since 1.0 2014-6-19 by sutroon
 */
class QueueController extends AppbaseController {

    public function index() {
        $this->display();
    }

    public function get_queue_search_data() {
        $search = I();
        if (!$this->isSuperAdmin) {
            $where['siteID'] = $this->loginData['siteID'];
        }
        if ($search['siteID']) {
            $where['siteID'] = $search['siteID'];
        }
        return array('where' => $where);
    }

    public function get_queue_list_json() {
        $search_data = $this->get_queue_search_data();
        $list = AddonD('Queue')->get_queue_list($search_data['where']);
        $this->ajaxReturn($list);
    }

    public function queue_export() {
        if (!$this->isSuperAdmin) {
            die('没有权限!');
        }
        $search_data = $this->get_queue_search_data();
        $list = AddonD('Queue')->scope('export')->where($search_data['where'])->select();
        if (!$list) {
            $this->ajaxMsg(false, '找不到符合条件的记录!');
        }
        sofn_excel_export($list);
    }

    /**
     * 获取队列列表
     */
    public function get_queue_json() {
        $fields = 'extension as id, extension as text';
        if ($this->isSuperAdmin) {
            if (I('siteID')) {
                $where['siteID'] = I('siteID');
            } else {
                $fields = array('extension as id', "concat(extension,'|',siteID) as text");
            }
        } else {
            $where['siteID'] = $this->loginData['siteID'];
        }
        $data = M('tcti_acd_queue')->cache(true)->where($where)->field($fields)->select();
        $this->ajaxReturn($data);
    }

    /**
     * 显示项目编辑表单
     */
    public function item_edit() {
        if (I('guide') == '1') {
            if (M('tgeneral_file')->where("exTags in ('moh','sounds')")->count('id') < 1) {
                $this->success('未上传语音文件', AddonU('VocFile/item_edit', 'guide=1'));
                exit;
            }
        }
        $id = I('id');
        if ($id) {
            $data = M('tcti_acd_queue')->find($id);
            $this->assign('data', $data);
        } else {
            $this->assign('data', array('siteID' => $this->loginData['siteID']));
        }
        $this->assign('guide', I('guide'));
        $this->display();
    }

    /**
     * 保存项目
     */
    public function item_save() {
        $params = new \Org\Su\Params();
        $params->addParam('siteID', 'number', '租户未选择!');
        $params->addParam('extension', 'number', 'ACD号码必须填写!');
        $params->addParam('overflowStrategy', 'require', '超时溢出标志必须选择!');
        $params->addParam('music', 'require', '欢迎语音必须选择!', false, I('music', 'default'));
        $params->addParam('maxlen', 'require', '最大排队数量必须填写!');
        $params->addParam('strategy', 'require', '振铃规则必须选择!');
        $params->addParam('retry', 'require', '重试间隔必须填写!');
        $params->addParam('timeout', 'require', '座席振铃超时时间必须填写!');
        $params->addParam('cwignore', 'require', '跳过示忙座席必须填写!');
        $params->addParam('remark', 'require', '备注必须选择!', true);
        $overflowStrategy = I('overflowStrategy');
        if ($overflowStrategy != '0') {
            $params->addParam('overflowTarget', 'require', '溢出目标必须选择!');
        }
        $extension = I('extension');
        if ($extension && strlen($extension) > 4) {
            $params->addError('队列号必须小于或等于4位!');
        }
        if ($params->hasError()) {
            $this->ajaxMsg(false, $params->getError());
        }
        $maxwait = I('maxwait');
        $params->addData('maxwait', $maxwait == '0' ? '' : $maxwait);
        $params->addData('descr', $extension); // 队列名称默认为队列号,防止乱填中文
        // 修正格式
        switch ($overflowStrategy) {
            case '0':
                $params->addData('overflowTarget', '');
                //$params->addData('dest', '');
                $params->addData('dest', 'app-blackhole,hangup,1');
                break;
            case 'queue':
                $params->addData('dest', 'ext-queues,' . $params->getParam('overflowTarget') . ',1');
                break;
            case 'extension':
                $params->addData('dest', 'from-did-direct,' . $params->getParam('overflowTarget') . ',1');
                break;
        }
        //$params->addData('monitor-format', I('monitor-format'));
        $params->addData('monitor-format', ''); // wav49
        $params->addData('monitor_type', 'b');
        $params->addData('cron_schedule', 'daily');
        $params->addData('autofill');
        $over_music = I('over_music');
        if (false !== ($pos = strrpos($over_music, '.'))) {
            $over_music = substr($over_music, 0, $pos);
        }
        $params->addData('over_music', $over_music);
        $id = I('id');
        $hasId = strlen($id) > 0;
        $M = M('tcti_acd_queue');
        if ($id) {
            $where['id'] = $id;
            $result = $M->where($where)->save($params->getParams());
        } else {
            // 检测ACD号码是否重复
            $where['extension'] = $extension;
            if ($M->where($where)->count() > 0) {
                $this->ajaxMsg(false, '[' . $extension . '] 已存在!');
            }
            $params->addData('createdTime', date('Y-m-d H:i:s'));
            $result = $M->add($params->getParams());
        }
        if ($result === false) {
            $this->ajaxMsg(false, '保存失败!');
        } else {
            // 如果是新增用户则自动注册asterisk
            $result = $this->save_asterisk($params->getParams(), $hasId ? 'update' : 'add');
            if ($result === false) {
                // 如果注册失败则删除已插入的记录
                $where['extension'] = $extension;
                $M->where($where)->delete();
                $this->ajaxMsg(false, '更新CTI基础服务失败!');
            } else {
                if ($hasId) {
                    $msg = $this->save_to_additional($params->getParams(), 2);
                    $this->force_need_reload();
                } else {
                    $msg = $this->save_to_additional($params->getParams(), 1);
                    if ($msg === true) {
                        $this->force_need_reload();
                    } else {
                        $this->ajaxMsg(false, $msg);
                    }
                }
            }
        }
        $this->ajaxMsg(true, '更新CTI基础服务成功!');
    }

    public function seat_edit($id = 0) {
        $data = AddonD('Queue')->find($id);
        $this->assign('data', $data);
        $this->display();
    }

    public function seat_edit_save() {
        $params = new \Org\Su\Params();
        $params->addParam('id', 'number', '参数有误!');
        $params->addParam('siteID', 'number', '租户未选择!');
        $params->addParam('extension', 'number', '队列号码必须填写!');
        $params->addData('members');
        $members = I('members');
        if ($members) {
            $params->addParam('trunkName', 'require', '远程座席中继未选择!');
        } else {
            $params->addData('trunkName');
        }
        if ($params->hasError()) {
            $this->ajaxMsg(false, $params->getError());
        }
        if ($members) {
            $arrmembers = explode("\n", $members);
            $arrmembers = array_unique($arrmembers);
            $members = implode("\n", $arrmembers);
            $params->updateParam('members', $members);
        }

        $data = $params->getParams();
        $advM = new \Think\Model\AdvModel('tcti_acd_queue');
        $result = $advM->save($data);
        if ($result === false) {
            $this->ajaxMsg(false, '保存失败!');
        } else {
            $oldmembers = I('oldmembers');
            if ($oldmembers) {
                $sql = $this->get_regist_members_sql($data['extension'], $oldmembers, $data['siteID'], false);
                if ($sql) {
                    $arr[] = $sql;
                }
            }
            // members
            if ($data['members']) {
                $sql = $this->get_regist_members_sql($data['extension'], $data['members'], $data['siteID']);
                if ($sql) {
                    $arr[] = $sql;
                }
            }
            if ($arr) {
                $advM->patchQuery($arr);
            }
            $this->force_need_reload();
            $this->ajaxMsg(true, '保存成功!');
        }
    }

    /**
     * 删除项目
     */
    public function item_delete($id = '') {
        if (!$id) {
            $this->ajaxMsg(false, '编号丢失!');
        }
        $M = M('tcti_acd_queue');
        $queues = $M->where(array('id' => array('in', $id)))->getField('extension', true);
        $errs = array();
        foreach ($queues as $queue) {
            $names = M('tcti_task_strategy')->where("outDefaultQueue='$queue' or outQueue='$queue' or outParam like '%:$queue;%'")->getField('name', true);
            if ($names) {
                $errs[$queue][] = '[外呼模式:' . (is_array($names) ? implode(',', $names) : $names) . ']';
            }
            $names = M('tcti_income_nav')->where("outQueue='$queue' or outParam like '%:$queue;%'")->getField('name', true);
            if ($names) {
                $errs[$queue][] = '[来话导航:' . (is_array($names) ? implode(',', $names) : $names) . ']';
            }
            $names = M('tcti_voice_menu')->where("outQueue='$queue' or outParam like '%:$queue;%'")->getField('id', true);
            if ($names) {
                $errs[$queue][] = '[语音菜单:' . (is_array($names) ? implode(',', $names) : $names) . ']';
            }
        }

        $queue = $data['extension'];
        if ($errs) {
            $msg = '';
            foreach ($errs as $key => $err) {
                $msg.="\n" . '队列 ' . $key . ' 被以下使用：' . "\n" . implode("\n", $err);
            }
            $this->ajaxMsg(false, $msg);
        }
        $msg = $M->delete($id);
        if (false === $msg) {
            $this->ajaxMsg(false, '删除失败!');
        }
        $str_queues = implode(',', $queues);
        // 删除alterisk表数据
        $M->execute("delete from asterisk.queues_config where extension in ($str_queues);");
        $M->execute("delete from asterisk.queues_details where id in ($str_queues)");
        //$msg = $this->save_to_additional($data, 0);
        $this->ajaxMsg(true);
    }

    /**
     * 保存到asterisk数据库
     * @param array $data
     * @param string $mode 模式,add=新增,update=更新
     * @since 1.0 2014-7-4 by sutroon
     */
    function save_asterisk($data, $mode) {
        $a = new \Think\Model\AdvModel();
        $result = $a->patchQuery($this->get_save_asterisk_sql($data, $mode));
        if ($result === false) {
            die('错误：' . $a->getDbError());
        }
        return $result;
    }

    /**
     * 获取注册asterisk的写入语句
     * @param array $data
     * @param string $mode 操作类型:update=更新,add=新增
     * @return array
     */
    private function get_save_asterisk_sql($data, $mode = 'update') {
        $arr = array();
        $extension = $data['extension'];
        // 写入queues_config表
        $params = new \Org\Su\Params();
        $params->addData('extension', $extension);
        $params->addData('descr', $data['descr']);
        $params->addData('grppre', '');
        $params->addData('alertinfo', '');
        $params->addData('ringing', '0');
        $params->addData('maxwait', $data['maxwait']);
        $params->addData('password', '');
        $params->addData('ivr_id', 'none');
        $params->addData('dest', $data['dest']); // ext-queues,2000,1
        $params->addData('cwignore', $data['cwignore']);
        $params->addData('qregex', '');
        $params->addData('agentannounce_id', '0');
        $params->addData('joinannounce_id', '0');
        $params->addData('queuewait', '1');
        $params->addData('monitor_type', $data['monitor_type']); // 录音模式 b
        if ($mode == 'update') {
            $arr[] = $params->get_update_sql('asterisk.queues_config', 'extension="' . $extension . '"', array('extension'));
        } else {
            $arr[] = $params->get_insert_sql('asterisk.queues_config');
        }
        // 在queues_detail新增记录
        $arrdetail = array(
            'announce-frequency' => '0',
            'announce-holdtime' => 'no',
            'autopause' => 'no', // 2015-7-3 kerry修正转队列不转的问题,增加此项目
            'joinempty' => 'yes', // yes 2015-7-3 kerry修正转队列不转的问题,yes改为strict; 2015-8-20 队列为空的时候会直接断线,而不是进入等待,改回yes
            'eventmemberstatus' => 'no',
            'monitor-join' => 'yes',
            'eventwhencalled' => 'no',
            'autofill' => $data['autofill'] == '1' ? 'yes' : 'no',
            'leavewhenempty' => 'no',
            'wrapuptime' => '0',
            'announce-position' => 'no',
            'monitor-format' => $data['monitor-format'], // wav
            'cron_schedule' => $data['cron_schedule'], // 复位队列状态 daily
            'music' => $data['music'], // xcall_0_001            
            'periodic-announce' => $data['over_music'], // 2015-4-14 新增 队列全满等待音
            'periodic-announce-frequency' => 'default' == $data['over_music'] ? '0' : '6',
            'queue-callswaiting' => 'silence/1',
            'queue-thankyou' => '',
            'queue-thereare' => 'silence/1',
            'queue-youarenext' => 'silence/1',
            'retry' => $data['retry'], // 14
            'strategy' => $data['strategy'], // roundrobin
            'timeout' => $data['timeout'], // 9
            'weight' => '0',
            'maxlen' => $data['maxlen'] // 7
//'member' => '' // Local/602@from-internal/n,0
        );
        if ('default' == $data['over_music']) {
            unset($arrdetail['over_music']);
        }
        if ($mode == 'update') {
            $fields = M('asterisk.queues_details')->where("id='$extension'")->getField("keyword, data", true);
            $this->sync_config_fields($fields, $arrdetail, array('TABLE' => 'asterisk.queues_details', 'DELETE_TPL' => 'id=' . $extension . ' and keyword in (%s)', 'FIELD_TPL' => "id, keyword, data", 'VALUE_TPL' => "('$extension','%s','%s')", 'MINUS_FIELDS' => array('periodic-announce'), 'ADD_FIELDS' => array('periodic-announce')));
            foreach ($arrdetail as $k => $v) {
                $arr[] = "update asterisk.queues_details set data='$v' where id='$extension' and keyword='$k';";
            }
        } else {
            foreach ($arrdetail as $k => $v) {
                $arr[] = "insert into asterisk.queues_details (id,keyword,data) values ('$extension','$k','$v');";
            }
        }
        return $arr;
    }

    function sync_config_fields($fields, $data, $options = array()) {
        $options = array_merge(array(
            'TABLE' => '',
            'DELETE_TPL' => "$key_field in (%s)",
            'FIELD_TPL' => "$key_field, $value_field",
            'VALUE_TPL' => "('%s','%s')",
            'MINUS' => TRUE,
            'ADD' => TRUE,
            'MINUS_FIELDS' => FALSE,
            'ADD_FIELDS' => FALSE
                ), $options);
        $M = M($options['TABLE']);
        if ($options['MINUS']) {
            $minus_fields = $options['MINUS_FIELDS'];
            if ($fields) {
                $arr_fields = $fields;
                foreach ($arr_fields as $key => $value) {
                    if (array_key_exists($key, $data) || ($minus_fields && !in_array($key, $minus_fields))) {
                        unset($arr_fields[$key]);
                    }
                }
            }
            if ($arr_fields) {
                $str_keys = implode("','", array_keys($arr_fields));
                $options['DELETE_TPL'] = sprintf($options['DELETE_TPL'], "'$str_keys'");
                $result = $M->where($options['DELETE_TPL'])->delete();
                if (false === $result) {
                    die('错误:' . $M->getDbError());
                }
            }
        }
        if ($options['ADD']) {
            $add_fields = $options['ADD_FIELDS'];
            if ($fields || $add_fields) {
                foreach ($data as $key => $value) {
                    if (($fields && array_key_exists($key, $fields)) || ($add_fields && !in_array($key, $add_fields))) {
                        unset($data[$key]);
                    }
                }
            }
            if ($data) {
                $values = false;
                foreach ($data as $key => $value) {
                    $values[] = sprintf($options['VALUE_TPL'], $key, $value);
                }
                $result = $M->execute('insert into ' . $options['TABLE'] . ' (' . $options['FIELD_TPL'] . ') values ' . implode(',', $values));
                if (false === $result) {
                    die('错误:' . $M->getDbError());
                }
            }
        }
    }

    // 2014-12-2 by sutroon
    private function get_regist_members_sql($account, $members, $siteID, $isLogin = true) {
        if (!$members) {
            return '';
        }
        $extensions = M('tuser_member')->where("siteID=$siteID and userType='SEAT'")->getField('userName', true);
        if ($members) {
            $members = explode(PHP_EOL, $members);

            if (!$members) {
                $members = null;
            }
            $members = array_unique($members);
            foreach (array_keys($members) as $key) {
                //trim it
                $members[$key] = trim($members[$key]);
                $this_member = preg_replace("/[^0-9#\,*]/", "", $members[$key]);
                if (empty($this_member)) {
                    unset($members[$key]);
                    continue;
                }
                // check if an agent (starts with a or A)
                $exten_prefix = strtoupper(substr($members[$key], 0, 1));
                $exten_context = "ext-agent"; // from-queue 2014-12-6 改为 ext-agent
                if (in_array($this_member, $extensions)) {
                    $exten_prefix = 'S'; // xcall工号默认是S
                    $exten_context = 'from-queue';
                    $this->login_extension_static($account, $this_member, false === $isLogin ? '' : 'login');
                    unset($members[$key]);
                    continue;
                }
                if (false === $isLogin) {
                    continue;
                }
                switch ($exten_prefix) {
                    case 'A':
                        $exten_type = 'Agent';
                        break;
                    case 'S':
                        $exten_type = 'SIP';
                        break;
                    case 'X':
                        $exten_type = 'IAX2';
                        break;
                    case 'Z':
                        $exten_type = 'ZAP';
                        break;
                    case 'D':
                        $exten_type = 'DAHDI';
                        break;
                    default;
                        $exten_type = 'Local';
                }

                $penalty_pos = strrpos($this_member, ",");
                if ($penalty_pos === false) {
                    $penalty_val = 0;
                } else {
                    $penalty_val = substr($this_member, $penalty_pos + 1); // get penalty
                    $this_member = substr($this_member, 0, $penalty_pos); // clean up ext
                    $this_member = preg_replace("/[^0-9#*]/", "", $this_member); //clean out other ,'s
                    $penalty_val = preg_replace("/[^0-9*]/", "", $penalty_val); // get rid of #'s if there
                    $penalty_val = ($penalty_val == "") ? 0 : $penalty_val;
                }

                // remove blanks // prefix with the channel

                switch ($exten_type) {
                    case 'Agent':
                    case 'SIP':
                    case 'IAX2':
                    case 'ZAP':
                    case 'DAHDI':
                        $members[$key] = "$exten_type/$this_member,$penalty_val";
                        break;
                    case 'Local':
                        $members[$key] = "$exten_type/$this_member@$exten_context/n,$penalty_val";
                }
            }
        }
        if (false === $isLogin) {
            return "delete FROM asterisk.queues_details WHERE id = " . $account . " AND keyword = 'member'";
        }
        //there can be multiple members
        if (isset($members)) {
            $count = 0;
            $members = array_unique($members);
            foreach ($members as $member) {
                // $fields[] = array($account, 'member', $member, $count);
                $fields[] = "('$account', 'member', '$member', $count)";
                $count++;
            }
        }
        $sql = '';
        if ($fields) {
            $sql = 'INSERT INTO asterisk.queues_details (id, keyword, data, flags) values ' . implode(',', $fields);
        }
        return $sql;
        //$sql = "SELECT data FROM asterisk.queues_details WHERE id = $account AND keyword = 'member' ORDER BY flags";
    }

    // 登入静态分机
    function login_extension_static($queue, $extension, $opt = 'login') {
        $astman = create_asmanager();
        $queue = $queue;
        $interface = 'SIP/' . $extension;
        if ($opt == 'login') {
            $result = $astman->Command('queue add member SIP/' . $extension . ' to ' . $queue . ' penalty 0 as ' . $extension . ' state_interface SIP/' . $extension);
            $isSuccess = strpos($result['data'], 'Added interface') !== false;
        } else {
            $result = $astman->QueueRemove($queue, $interface); // 移除队列
            $isSuccess = $result['Response'] == 'Success';
        }
        sleep(0.5);
        return array('result' => $isSuccess, 'Message' => $result['Message']);
    }

    function dongtai() {
        /* if ($astman) {
          $dynmembers = array_unique($dynmembers);
          foreach($dynmembers as $member){
          $mem = explode(',',$member);
          if (isset($mem[0]) && trim($mem[0]) != '') {
          $penalty = isset($mem[1]) && ctype_digit(trim($mem[1])) ? $mem[1] : 0;
          $astman->database_put('QPENALTY/'.$account.'/agents',trim($mem[0]),trim($penalty));
          }
          }
          $astman->database_put('QPENALTY/'.$account,'dynmemberonly',$dynmemberonly);
          }
         *
         */
    }

    function save_to_additional($data, $activated = true) {
        return true; // 已由系统reload接管 2015-4-14 SoChishun
        if (!$data) {
            return '参数有误!';
        }
        if (!file_exists(queues_additional_path)) {
            return '配置文件不存在';
        }
        if (!is_writable(queues_additional_path)) {
            return '配置文件不允许读写';
        }

        $file_content = file_get_contents(queues_additional_path);
        if ($activated) {
            if (2 == $activated) {
                if (strstr($file_content, '[' . $data['extension'] . ']')) {
                    $file_content = ereg_replace('\[' . $data['extension'] . '[^\[]*[^\[]?', "", $file_content);
                    file_put_contents(queues_additional_path, $file_content);
                }
            }
            if (strstr($file_content, '[' . $data['extension'] . ']')) {
                return '配置文件中已包含此队列号码';
            }
            $content = "\n\n[{queueno}]\nannounce-frequency={announce-frequency}\nannounce-holdtime={announce-holdtime}\njoinempty={joinempty}\neventmemberstatus={eventmemberstatus}\neventwhencalled={eventwhencalled}\nautofill={autofill}\nleavewhenempty={leavewhenempty}\nwrapuptime={wrapuptime}\nannounce-position={announce-position}\nmusic={music}\nperiodic-announce-frequency={periodic-announce-frequency}\nqueue-callswaiting={queue-callswaiting}\nqueue-thereare={queue-thereare}\nqueue-youarenext={queue-youarenext}\nretry={retry}\nstrategy={strategy}\ntimeout={timeout}\nweight={weight}\nmaxlen={maxlen}\nperiodic-announce={over_music}";
            $content = str_replace('{queueno}', $data['extension'], $content);
            $content = str_replace('{announce-frequency}', '0', $content); // 0
            $content = str_replace('{announce-holdtime}', 'no', $content); // no
            $content = str_replace('{joinempty}', 'yes', $content); // yes
            $content = str_replace('{eventmemberstatus}', 'no', $content); // no
            $content = str_replace('{eventwhencalled}', 'no', $content); // no
            $content = str_replace('{autofill}', $data['autofill'] == '1' ? 'yes' : 'no', $content); // yes
            $content = str_replace('{leavewhenempty}', 'no', $content); // no
            $content = str_replace('{wrapuptime}', '0', $content); // 0
            $content = str_replace('{announce-position}', 'no', $content); // no
            $content = str_replace('{music}', $data['music'], $content); // xcall_0_001
            $content = str_replace('{queue-callswaiting}', 'silence/1', $content); // silence/1
            $content = str_replace('{queue-thereare}', 'silence/1', $content); // silence/1
            $content = str_replace('{queue-youarenext}', 'queue-youarenext', $content); // queue-youarenext
            $content = str_replace('{retry}', $data['retry'], $content); // 14
            $content = str_replace('{strategy}', $data['strategy'], $content); // leastrecent
            $content = str_replace('{timeout}', $data['timeout'], $content); // 9
            $content = str_replace('{weight}', '0', $content); // 0
            $content = str_replace('{maxlen}', $data['maxlen'], $content); // 7
            if ($data['over_music'] == 'default') {
                $content = str_replace('{periodic-announce-frequency}', '0', $content); // 0
                $content = str_replace("\nperiodic-announce={over_music}", '', $content);
            } else {
                $content = str_replace('{periodic-announce-frequency}', '6', $content); // 0
                $content = str_replace('{over_music}', $data['over_music'], $content);
            }
            $fp = fopen(queues_additional_path, 'a+');
            fwrite($fp, $content);
            fclose($fp);
        } else {
            if (strstr($file_content, '[' . $data['extension'] . ']')) {
                $file_content = ereg_replace('\[' . $data['extension'] . '[^\[]*[^\[]?', "", $file_content);
                file_put_contents(queues_additional_path, $file_content);
            }
        }
        return true;
    }

}
